import type { ElementSelectors } from '../../lib/abstract'
import type { EventBindingConfig } from '../../lib/abstract/base_destructible'
import type { IconId } from '../../lib/icons/types/interfaces'
import type {
  ComponentStyleIdType,
  ThemeType,
} from '../../types/interfaces'
import type { NavbarProps, NavItem, UserMenuItem } from './types'
import { UIComponent } from '../../lib/abstract'
import { IconService } from '../../lib/icons'
import { ICON_IDS } from '../../lib/icons/types/constants'
import { ToolKit } from '../../lib/utils/toolkit'
import { BodyClasses, ComponentStyleId, logger } from '../../types/constants'
import { ThemeSourceMode } from '../../types/interfaces'
import { styles } from './styles'
import { DEFAULT_NAVBAR_PROPS } from './types'

export class Navbar extends UIComponent<NavbarProps> {
  id: string = 'navbar'
  readonly description: string = '页面顶部导航菜单栏（支持折叠）'
  readonly styleId: string = ComponentStyleId[this.name]
  readonly iconService: IconService = IconService.getInstance()
  private theme: ThemeType = ToolKit.browser.theme.getCurrentTheme()
  private observer: MutationObserver | null = null
  private isCollapsed: boolean = false
  // 是否为移动端模式
  private isMobileMode: boolean = false
  // 是否为移动端展开状态
  private isMobileExpanded: boolean = false

  get name(): ComponentStyleIdType {
    return 'Navbar'
  }

  get className(): string {
    return 'custom-navbar'
  }

  get eventConfigs(): EventBindingConfig[] {
    return [
      // 品牌点击事件
      {
        selector: this.getElement('brand'),
        eventType: 'click',
        handler: () => this.handleBrandClick(),
        meta: { category: 'brand' },
      },
      // 导航项点击事件
      {
        selector: this.getElement('navItems'),
        childSelector: '.nav-dropdown-item a',
        eventType: 'click',
        handler: (e: any) => this.handleNavItemClick(e),
        meta: { category: 'navigation' },
      },
      // 用户菜单点击事件
      {
        selector: this.getElement('userMenu'),
        childSelector: '.user-menu-link',
        eventType: 'click',
        handler: (e: any) => this.handleUserItemClick(e),
        meta: { category: 'user' },
      },
      // 折叠按钮点击事件
      {
        enabled: this.props.enableCollapse,
        selector: this.getElement('collapseToggle'),
        eventType: 'click',
        handler: () => this.toggleCollapse(),
        meta: { category: 'collapse' },
      },
      // ============================== 移动端事件 ==============================
      // 导航一级菜单点击事件
      {
        enabled: this.isMobileMode,
        selector: this.getElement('navItems'),
        childSelector: '.nav-item-link',
        eventType: 'click',
        handler: (e: any) => this.handleNavClick(e),
        meta: { category: 'navigation' },
      },
      // 用户菜单下拉图标点击事件
      {
        enabled: this.isMobileMode,
        selector: this.getElement('userMenu'),
        childSelector: '> .nav-item-icon',
        eventType: 'click',
        handler: (e: any) => this.handleUserIconClick(e),
        meta: { category: 'user' },
      },
      // 移动端菜单切换按钮点击事件
      {
        enabled: this.isMobileMode,
        selector: this.getElement('mobileToggle'),
        eventType: 'click',
        handler: () => this.toggleMobileExpand(),
        meta: { category: 'mobile-menu' },
      },
    ]
  }

  constructor(props: NavbarProps) {
    super({
      ...DEFAULT_NAVBAR_PROPS,
      ...props,
    })

    // 初始化折叠状态
    this.isCollapsed = this.props.initiallyCollapsed || false

    // 初始化移动端
    this.initMobileState()

    // 注册样式
    this.registerStyles()
  }

  ELEMENT_SELECTORS: ElementSelectors = {
    navbar: { selector: `.${this.className}`, dynamic: false, unique: false, isRoot: true },
    brand: { selector: `.brand-container`, dynamic: false, unique: false },
    navItems: { selector: `.nav-container .nav-item`, dynamic: false, unique: false },
    userMenu: { selector: `.user-container`, dynamic: false, unique: false },
    collapseToggle: { selector: `.navbar-collapse-toggle`, dynamic: false, unique: false },
    navbarContent: { selector: `.navbar-content`, dynamic: false, unique: false },
    mobileToggle: { selector: '.mobile-menu-toggle', dynamic: false, unique: false },
  }

  /**
   * 初始化移动端相关状态
   */
  private initMobileState(): void {
    if (ToolKit.browser.platform.isMobileMode()) {
      this.isMobileMode = true
    }
  }

  /**
   * 设置当前激活的导航项
   */
  setActiveItem(id: string): void {
    const $navItems = this.getElement('navItems')

    if (!$navItems || !$navItems.length)
      return

    $navItems.each((_index, element) => {
      const $item = $(element)
      const itemId = $item.data('id')

      $item.toggleClass(`active`, itemId === id)
    })
  }

  /**
   * 渲染折叠切换按钮
   */
  private renderCollapseToggle(): string {
    if (!this.props.enableCollapse)
      return ''

    const title = this.isCollapsed ? '展开导航栏' : '折叠导航栏'

    return `
      <button 
        class="navbar-collapse-toggle" 
        aria-label="${title}"
        aria-expanded="${!this.isCollapsed}"
        title="${title}"
      >
        <img 
          class="collapse-toggle-icon" 
          src="${this.iconService.api.icon.asDataUrl(ICON_IDS.action.fold, { theme: this.theme })}" 
          alt="${title}" 
        />
      </button>
    `
  }

  /**
   * 渲染导航项
   */
  private renderNavItem(item: NavItem): string {
    const { activeId } = this.props as NavbarProps
    const isActive = item.id === activeId
    const hasChildren = item.children && item.children.length > 0

    return `
      <li 
        class="nav-item ${isActive ? `active` : ''}" 
        data-id="${item.id}"
        ${item.disabled ? 'data-disabled="true"' : ''}
      >
        <a 
          class="nav-item-link" 
          ${item.path && !item.external ? `href="${item.path}"` : ''}
          ${item.external && item.path ? `href="${item.path}" target="_blank" rel="noopener noreferrer"` : ''}
          ${item.disabled ? 'aria-disabled="true"' : ''}
        >
          ${item.iconType
            ? `
              ${this.iconService.api.icon.asSvg(item.iconType, { className: 'nav-item-icon' })}
            `
            : ''}
          ${item.label}
          ${hasChildren ? `<img class="nav-item-icon" src="${this.iconService.api.icon.asDataUrl(ICON_IDS.navigation.arrowsDown, { theme: this.theme })}" data-icon-type="arrowsDown" alt="下拉菜单" />` : ''}
        </a>
        ${
          hasChildren
            ? `
              <ul class="nav-dropdown">
                ${item.children!.map(child => this.renderDropdownItem(child)).join('')}
              </ul>
            `
            : ''
        }
      </li>
    `
  }

  /**
   * 渲染下拉菜单项
   */
  private renderDropdownItem(item: NavItem): string {
    return `
      <li 
        class="nav-dropdown-item ${item.disabled ? `disabled` : ''}" 
        data-id="${item.id}"
        ${item.disabled ? 'data-disabled="true"' : ''}
      >
        <a 
          ${item.path && !item.external ? `href="${item.path}"` : ''}
          ${item.external && item.path ? `href="${item.path}" target="_blank" rel="noopener noreferrer"` : ''}
          ${item.disabled ? 'aria-disabled="true"' : ''}
        >
          ${item.iconType
            ? `
            <img class="nav-item-icon" 
              src="${this.iconService.api.icon.asDataUrl(item.iconType, { theme: this.theme })}" 
              data-icon-type="${item.iconType}" 
              alt="${item.label}图标" 
            />`
            : ''}
          ${item.label}
        </a>
      </li>
    `
  }

  /**
   * 渲染用户菜单
   */
  private renderUserMenu(): string {
    const { userAvatar, userAvatarLink, userMenuItems, userName } = this.props as NavbarProps

    return `
      <div class="user-container">
        ${userAvatar
          ? `
            <a href="${userAvatarLink || '#'}" class="user-avatar-link" target="_blank" rel="noopener noreferrer">
              <img class="user-avatar" src="${userAvatar}" alt="${userName}" />
            </a>
          `
          : ''}
        <span class="user-name">${userName}</span>
        ${userMenuItems && userMenuItems.length > 0
          ? `
            <img class="nav-item-icon" src="${this.iconService.api.icon.asDataUrl(ICON_IDS.navigation.arrowsDown, { theme: this.theme })}" data-icon-type="arrowsDown" alt="下拉菜单"/>
            <ul class="user-menu-list">
              ${userMenuItems.filter(item => item.enabled !== false).map(item => this.renderUserMenuItem(item)).join('')}
            </ul>
          `
          : ''}
      </div>
    `
  }

  /**
   * 渲染用户菜单项
   */
  private renderUserMenuItem(item: UserMenuItem): string {
    return `
    <li class="user-menu-item">
      <a href="${item.path || '#'}"
         class="user-menu-link"
         data-id="${item.id}"
         ${item.external ? 'target="_blank" rel="noopener noreferrer"' : ''}
      >
       ${item.iconType
          ? `
            <img class="user-menu-icon" 
              src="${this.iconService.api.icon.asDataUrl(item.iconType, { theme: this.theme })}" 
              data-icon-type="${item.iconType}" 
              alt="${item.label}图标" 
            />`
          : ''}
        <span class="user-menu-text">${item.label}</span>
      </a>
    </li>
  `
  }

  render(): string {
    const { id, items, showBrand, brandLogo, brandName, showUserMenu, enableCollapse, initiallyCollapsed } = this.props as NavbarProps

    return `
      <nav class="${this.className} ${id} ${initiallyCollapsed ? BodyClasses.IS_COLLAPSED : ''} ${this.isMobileExpanded ? `${BodyClasses.MOBILE_EXPANDED}` : ''}">
        <div class="navbar-content">
          ${
            showBrand
              ? `
                <div class="brand-container">
                  ${brandLogo ? `<img class="brand-logo" src="${brandLogo}" alt="${brandName}" />` : ''}
                  <span class="brand-name">${brandName}</span>
                </div>
              `
              : ''
          }
          <ul class="nav-container">
            ${items.map(item => this.renderNavItem(item)).join('')}
          </ul>
          ${showUserMenu ? this.renderUserMenu() : ''}
        </div>
        ${enableCollapse ? this.renderCollapseToggle() : ''}
        ${this.isMobileMode ? this.renderMobileToggle() : ''}
      </nav>
    `
  }

  private renderMobileToggle(): string {
    return `
      <button class="mobile-menu-toggle ${this.isMobileExpanded ? '' : `${BodyClasses.IS_COLLAPSED}`}" 
              aria-label="${this.isMobileExpanded ? '收起菜单' : '展开菜单'}">
        <img class="toggle-icon" 
             src="${this.getMobileMenuIcon()}" 
             alt="菜单" />
      </button>
    `
  }

  /**
   * 获取移动端菜单图标
   */
  getMobileMenuIcon(): string {
    return this.isMobileExpanded
      ? this.iconService.api.icon.asDataUrl(ICON_IDS.action.close, { theme: this.theme })
      : this.iconService.api.icon.asDataUrl(ICON_IDS.other.menu, { theme: this.theme })
  }

  bindEvents(): void {
    this.autoBindEvents()
    this.initThemeObserver()
  }

  /**
   * 切换折叠状态
   */
  toggleCollapse(): void {
    const newCollapsedState = !this.isCollapsed
    this.setCollapsed(newCollapsedState)
  }

  // 切换移动端展开状态
  private toggleMobileExpand(): void {
    this.isMobileExpanded = !this.isMobileExpanded
    this.updateMobileExpandState()
  }

  // 更新移动端状态
  private updateMobileExpandState(): void {
    this.getElement('navbar')
      ?.toggleClass(BodyClasses.MOBILE_EXPANDED, this.isMobileExpanded)
    this.getElement('mobileToggle')
      ?.toggleClass(BodyClasses.IS_COLLAPSED, !this.isMobileExpanded)
      .attr('aria-expanded', String(this.isMobileExpanded))
      .find('.toggle-icon')
      .attr('src', this.getMobileMenuIcon())
  }

  /**
   * 设置折叠状态
   */
  setCollapsed(collapsed: boolean): void {
    if (this.isCollapsed === collapsed)
      return

    this.isCollapsed = collapsed
    this.updateCollapseState(collapsed)

    // 触发回调
    if (this.props.onCollapseChange) {
      this.props.onCollapseChange(collapsed)
    }
  }

  /**
   * 更新折叠状态 UI
   */
  private updateCollapseState(collapsed: boolean): void {
    const $content = this.getElement('navbarContent')
    const $toggle = this.getElement('collapseToggle')

    if ($content && $toggle) {
      const $navbar = $toggle.closest(this.selector)
      // 更新类名
      $navbar.toggleClass(BodyClasses.IS_COLLAPSED, collapsed)

      // 更新 ARIA 属性
      $toggle.attr('aria-expanded', String(!collapsed))

      // 更新标题
      const title = collapsed ? '展开导航栏' : '折叠导航栏'
      $toggle.attr('title', title).attr('aria-label', title)
    }
  }

  /**
   * 处理品牌点击事件
   */
  private handleBrandClick() {
    const { brandLink } = this.props as NavbarProps
    if (brandLink) {
      ToolKit.browser.url.openNewTab(brandLink)
    }
  }

  /**
   * 处理导航一级菜单点击事件
   */
  private handleNavClick(e: JQuery.ClickEvent) {
    const $target = $(e.currentTarget)
    const $item = $target.closest('.nav-item')
    const $dropdown = $item.find('.nav-dropdown')

    if ($dropdown.length) {
      $dropdown.toggleClass(BodyClasses.IS_EXPANDED)
    }
  }

  /**
   * 处理导航项点击事件
   */
  private handleNavItemClick(e: JQuery.ClickEvent) {
    const { onItemClick } = this.props as NavbarProps

    const $target = $(e.currentTarget)
    const $item = $target.closest('.nav-dropdown-item')
    const id = $item.data('id')
    const disabled = $item.data('disabled')

    if (disabled) {
      e.preventDefault()
      e.stopPropagation()
      return
    }

    const { items } = this.props as NavbarProps
    const item = this.findItemById(items, id)

    if (item && onItemClick) {
      onItemClick(item)
    }
  }

  /**
   * 处理用户菜单项点击事件
   */
  private handleUserItemClick(e: JQuery.ClickEvent) {
    const { userMenuItems = [], onUserMenuItemClick } = this.props as NavbarProps

    e.preventDefault()

    const $target = $(e.currentTarget)
    const id = $target.data('id')
    const item = userMenuItems.find(i => i.id === id)

    if (item) {
      // 优先使用自定义回调
      if (onUserMenuItemClick) {
        onUserMenuItemClick(item)
      }
      // 没有回调则执行默认跳转
      else if ($target.attr('href') !== '#') {
        ToolKit.browser.url.openTab($target.attr('href')!)
      }
    }
  }

  /**
   * 处理用户菜单下拉图标点击事件
   */
  private handleUserIconClick(e: JQuery.ClickEvent) {
    const $target = $(e.currentTarget)
    const $list = $target.closest('.user-container').find('.user-menu-list')

    if ($list.length) {
      $list.toggleClass(BodyClasses.IS_EXPANDED)
    }
  }

  /**
   * 初始化主题观察器
   */
  private initThemeObserver(): void {
    if (this.observer)
      return // 防止重复初始化

    const config: MutationObserverInit = {
      attributes: true,
      attributeFilter: ['style'],
      attributeOldValue: true,
    }

    try {
      this.observer = new MutationObserver(this.handleThemeMutation)
      this.observer.observe(document.documentElement, config)
      this.observers.add(this.observer)
    }
    catch (error: any) {
      logger.error(`[${this.name}] 主题观察器初始化失败`, error)
    }
  }

  /**
   * 处理主题变化
   */
  private handleThemeMutation: MutationCallback = (mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
        const newTheme = ToolKit.browser.theme.getCurrentTheme(ThemeSourceMode.INLINE)
        if (newTheme !== this.theme) {
          this.theme = newTheme
          this.updateIcons()
        }
      }
    })
  }

  /**
   * 根据ID查找导航项
   */
  private findItemById(items: NavItem[], id: string): NavItem | undefined {
    for (const item of items) {
      if (item.id === id) {
        return item
      }

      if (item.children) {
        const found = this.findItemById(item.children, id)
        if (found) {
          return found
        }
      }
    }
    return undefined
  }

  /**
   * 更新所有图标
   */
  private updateIcons() {
    // 更新导航项图标
    this.getElement('navItems')?.find('.nav-item-icon').each((_, el) => {
      const $icon = $(el)
      const iconType = $icon.data('icon-type')
      this.setIcon($icon, iconType)
    })

    // 更新用户菜单图标
    this.getElement('userMenu')?.find('.user-menu-icon, .nav-item-icon').each((_, el) => {
      const $icon = $(el)
      const iconType = $icon.data('icon-type')
      this.setIcon($icon, iconType)
    })
  }

  /**
   * 设置指定图标类型的图标到指定元素
   */
  private setIcon($element: JQuery<HTMLElement>, iconType: IconId) {
    if (!iconType)
      return

    $element.attr('src', this.iconService.api.icon.asDataUrl(iconType, { theme: this.theme }))
  }

  getStyles(): string {
    return styles(this.className)
  }

  reset(): void {
    super.reset()
  }

  handleCleanupReferences(): void {
    this.observer = null
  }
}
